#include <bits/stdc++.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define BUFFER_SIZE 1024
#define MAX_CLIENTS 100

std::vector<int> client_sockets;
std::mutex clients_mutex;

void broadcast(const std::string& message) {
    for (int client_socket : client_sockets) {
        send(client_socket, message.c_str(), message.size(), 0);
    }
}

void handle_client(int client_socket) {
    char buffer[BUFFER_SIZE];
    sockaddr_in client_addr;
    socklen_t client_addr_len = sizeof(client_addr);

    // 获取客户端地址
    getpeername(client_socket, (struct sockaddr*)&client_addr, &client_addr_len);

    // 向所有客户端广播新客户端连接的消息
    std::string connect_message = inet_ntoa(client_addr.sin_addr) + std::string(" is connected");
    broadcast(connect_message);

    while (true) {
        int bytes_received = recv(client_socket, buffer, BUFFER_SIZE, 0);
        if (bytes_received <= 0) break;

        buffer[bytes_received] = '\0';
        std::string response = inet_ntoa(client_addr.sin_addr) + std::string(": ") + std::string(buffer);
        broadcast(response);
    }

    // 从客户端列表中移除
    std::lock_guard<std::mutex> lock(clients_mutex);
    auto new_end = std::remove(client_sockets.begin(), client_sockets.end(), client_socket);
    client_sockets.erase(new_end, client_sockets.end());
    close(client_socket);
}

int main(int argc, char* argv[]) {
    if (argc != 2) {
        std::cerr << "Usage: " << argv[0] << " <port>" << std::endl;
        return 1;
    }

    int port = std::atoi(argv[1]);
    int server_sock = socket(AF_INET, SOCK_STREAM, 0);
    sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(port);

    bind(server_sock, (struct sockaddr*)&server_addr, sizeof(server_addr));
    listen(server_sock, MAX_CLIENTS);

    std::cout << "Server is running." << std::endl;

    while (true) {
        int client_sock = accept(server_sock, nullptr, nullptr);
        std::lock_guard<std::mutex> lock(clients_mutex);
        client_sockets.push_back(client_sock);

        /*
        std::thread：   这是C++标准库中的一个类，用于创建线程。当你创建一个std::thread对象时，
                        它会启动一个新的线程来执行指定的函数。
        handle_client：这是你希望在新线程中执行的函数。在这个例子中，handle_client是一个函数，
                       它接受一个整数参数（客户端套接字的文件描述符），并处理与该客户端的通信。
        client_sock：这是传递给handle_client函数的参数。在这个上下文中，client_sock是通过accept()
                     函数获得的客户端套接字的文件描述符。它表示与客户端的连接。
        .detach()：这是std::thread对象的一个成员函数。调用detach()后，线程将继续在后台运行，
                   而主线程可以继续执行其后续代码，不会等待这个线程结束。
                   这与join()不同，join()会阻塞主线程，直到被join()的线程完成。
            如果你不调用detach()，handle_client函数不会在主线程中执行，它会在你创建的线程中执行。
            detach后，主线程就不会管子线程后，join()不在等待子线程。销毁std::thread对象时，也不管
            子线程对象啦。在服务器程序中，通常使用detach()来处理每个客户端连接，因为服务器需要同时
            处理多个客户端连接，而不是等待每个连接完成再处理下一个连接。
        */
        std::thread(handle_client, client_sock).detach();
    }

    close(server_sock);
    return 0;
}

